home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 …SCII & the Runetime Code / ADC Developer CD (1992-07) (''Butch ASCII And The Runtime Code'')_iso / Dev.CD 199207.iso / Tools & Apps / OS⁄Toolbox / Apple Events / AE Word Services 1.0d6 / Writeswell Jr. Source / DoChecking.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-23  |  11.1 KB  |  477 lines  |  [TEXT/KAHL]

  1. /* DoChecking.c
  2.  * Functions that actually do the calls to the Word Services servers.
  3.  * ©1992 Working Software, Inc.
  4.  * This source code is copyrighted.  Permission is granted to use the Word Services
  5.  * portion of the Writeswell Jr. source code in your own programs, but you 
  6.  * may not distribute the Writeswell Jr. word-processor code as a 
  7.  * commercial product.  If you modify the code, please do not call it 
  8.  * Writeswell Jr. (or Writeswell.)  This will ensure that people understand the 
  9.  * program and don’t have to deal with a number of different versions with 
  10.  * who-knows-what going on in the code.
  11.  * 
  12.  * Writeswell Jr. and Writeswell are trademarks of Working Software, Inc.
  13.  * 28 Dec 91 Mike Crawford
  14.  */
  15.  
  16. #include <Aliases.h>
  17. #include <Processes.h>
  18. #include <AppleEvents.h>
  19. #include <AEObjects.h>
  20. #include <AEPackObject.h>
  21. #include <AERegistry.h>
  22. #include "TBConstants.h"
  23. #include "TBGlobals.h"
  24. #include "WordServices.h"
  25. #include "AppEvents.h"
  26. #include "ObWind.h"
  27. #include "Gripe.h"
  28. #include "Prefs.h"
  29. #include "DoChecking.h"
  30. #include "FindProcess.h"
  31.  
  32. OSErr LaunchSpeller( AliasHandle aliasHdl );
  33.  
  34. OSErr DoSpellCheck( short serviceNumber )
  35. {
  36.     OSErr            err;
  37.     AEDesc            docSpecifier;
  38.     AEDesc            textDescriptor;
  39.     AEDesc            textSpecifier;
  40.     AEAddressDesc    spellerAddr;
  41.     AppleEvent        btchEvent;
  42.     AppleEvent        replyEvent;
  43.     WWJrPrefsHdl    prefHdl;
  44.     ServiceType        servType;
  45.  
  46.     err = OpenSpeller( serviceNumber, &spellerAddr, &servType );
  47.     if ( err ){
  48.         DebugStr( "\pOpenSpeller failed to connect with speller" );
  49.         return err;
  50.     }
  51.  
  52.     switch ( servType ){
  53.         case kBatchService:
  54.             err = DoBatchCheck( &spellerAddr );
  55.             if ( err ){
  56.                 Gripe( "\pDoBatchCheck failed" );
  57.                 return err;
  58.             }
  59.             break;
  60.         case kInteractiveService:
  61.             Gripe( "\pInteractive service is not implemented yet" );
  62.             return noErr;
  63.             break;
  64.         default:
  65.             Gripe( "\pBad service type code in preferences file" );
  66.             return noErr;
  67.     }
  68.  
  69.     return noErr;
  70. }
  71.     
  72. OSErr DoBatchCheck( AEAddressDesc *spellerAddrPtr )
  73. {
  74.     OSErr            err;
  75.     AEDesc            docSpecifier;
  76.     AEDesc            textDescriptor;
  77.     AEDesc            textSpecifier;
  78.     AppleEvent        btchEvent;
  79.     AppleEvent        replyEvent;
  80.     WWJrPrefsHdl    prefHdl;
  81.  
  82.     /* We make an object specifier that refers to _our_own_ window
  83.      */
  84.  
  85.     err = BuildWindowSpecifier( &docSpecifier, 1 );
  86.     if ( err ){
  87.         Gripe( "\pBuildWindowDescriptor failed" );
  88.         return err;
  89.     }
  90.  
  91.     /* Since we are spellchecking everything, we make the window descriptor into 
  92.      * a descriptor for the one text item in the window.
  93.      */
  94.     
  95.     err = CreateOffsetDescriptor( 1, &textDescriptor );        /* First item in container */
  96.     if ( err ){
  97.         Gripe( "\pCreateOffsetDescriptor failed" );
  98.         return err;
  99.     }
  100.     
  101.     err = CreateObjSpecifier( cText,
  102.                                 &docSpecifier,
  103.                                 formAbsolutePosition,
  104.                                 &textDescriptor,
  105.                                 true,                        /* Dispose input descriptors */
  106.                                 &textSpecifier );
  107.     if ( err ){
  108.         Gripe( "\pCreateObjSpecifer failed" );
  109.         return err;
  110.     }
  111.     
  112.     prefHdl = GetPrefHandle();
  113.     if ( !prefHdl ){
  114.         Gripe( "\pCannot get preferences handle" );
  115.         return resNotFound;
  116.     }
  117.     
  118.     if ( (*prefHdl)->checkSel ){
  119.         /* Make a formRange descriptor that gives the selection range */
  120.  
  121.         Gripe( "\pSelection-only checking is not yet implemented" );
  122.         return noErr;
  123.     }
  124.  
  125.     /* Create the event to send to the speller */
  126.     
  127.     err = AECreateAppleEvent( kWordServicesClass,
  128.                                 kWSBatchCheckMe,
  129.                                 spellerAddrPtr,
  130.                                 kAutoGenerateReturnID,
  131.                                 kAnyTransactionID,
  132.                                 &btchEvent );
  133.     
  134.     if ( err ){
  135.         Gripe( "\pcreate btch event failed" );
  136.         return err;
  137.     }
  138.     err = AEDisposeDesc( spellerAddrPtr );
  139.     if ( err ){
  140.         Gripe( "\pAEDisposeDesc failed" );
  141.         return err;
  142.     }
  143.     
  144.     /* Insert the object specifier as the direct object of the batch event */
  145.  
  146.     err = AEPutParamDesc( &btchEvent,
  147.                             keyDirectObject,
  148.                             &textSpecifier );
  149.     if ( err ){
  150.         Gripe( "\pAEPutParamDesc failed to put direct object on batch event" );
  151.         return err;
  152.     }
  153.     err = AEDisposeDesc( &textSpecifier );
  154.     if ( err ){
  155.         Gripe( "\pAEDisposeDesc failed" );
  156.         return err;
  157.     }
  158.  
  159.     /* Send the event.  We await the reply, so that if there is a failure of some
  160.      * sort in the initial connection, we can alert the user right away.  The timeout
  161.      * value to use here should be as long as one would care to have a user wait for
  162.      * the completion of a menu command.  Since we expect that the speller is on a local
  163.      * machine in this case, and should be able to respond immediately, we just give
  164.      * a few seconds for the timeout.
  165.      *
  166.      * We should assign an idle proc to spin the cursor.  Even better would be a progress
  167.      * dialog that says "Contacting speller" or some such, with an animated display that
  168.      * shows the time elapsed relative to the total timeout, so the user will know how
  169.      * long she may have to wait
  170.      */
  171.  
  172. #define kFewSeconds 300
  173.     
  174.     err = AESend( &btchEvent,
  175.                     &replyEvent,
  176.                     kAEWaitReply + kAECanInteract + kAECanSwitchLayer,
  177.                     kAENormalPriority,
  178.                     kFewSeconds,
  179.                     (IdleProcPtr)NULL,
  180.                     (EventFilterProcPtr)NULL );
  181.     
  182.     if ( err ){
  183.         Gripe( "\psend btch event failed" );
  184.         return err;
  185.     }
  186.     err = AEDisposeDesc( &btchEvent );
  187.     if ( err ){
  188.         Gripe( "\pAEDisposeDesc failed" );
  189.         return err;
  190.     }
  191.     
  192.     /* Now the event has been sent.  There is nothing more that we have to actually do
  193.      * on our own initiative to accomplish the spelling; we just sit back and respond
  194.      * to events.  In particular, we don't remember that spelling is taking place - once
  195.      * the spelling is done, we will just start seeing events from the user (mouse and
  196.      * key clicks and so on
  197.      */
  198.     
  199.     return noErr;
  200. }
  201.  
  202. OSErr OpenSpeller( short serviceNumber,
  203.                     AEAddressDesc *spellerAddrPtr,
  204.                     ServiceType *servTypePtr )
  205. {
  206.     WWJrPrefsHdl    prefHdl;
  207.     short            servID;
  208.     AliasHandle        aliasHdl;
  209.     short            curFile;
  210.     OSType            signature;
  211.     ProcessSerialNumber psn;
  212.     ProcessInfoRec        pInfo;
  213.     OSErr            err;
  214.     
  215.     prefHdl = GetPrefHandle();
  216.     if ( !prefHdl ){
  217.         Gripe( "\pCannot get prefs handle" );
  218.         return resNotFound;
  219.     }
  220.     
  221.     servID = gServItemID[ serviceNumber - 1 ];        /* C arrays start at 0 */
  222.     
  223.     *servTypePtr = (*prefHdl)->serviceType[ servID - kServiceBaseID ];
  224.  
  225.     curFile = CurResFile();
  226.     UseResFile( gPrefFileRefNum );
  227.     
  228.     aliasHdl = (AliasHandle)GetResource( rAliasType, servID );
  229.  
  230.     UseResFile( curFile );
  231.  
  232.     if ( !aliasHdl ){
  233.         Gripe( "\pCannot get alias handle for service" );
  234.         return resNotFound;
  235.     }
  236.     
  237.     /* See if the speller is out there */
  238.     signature = (*aliasHdl)->userType;
  239.  
  240.     if ( !FindAProcess( signature, &psn, &pInfo, (FSSpecPtr)NULL, (StringPtr)NULL ) ){
  241.  
  242.         EventRecord event;
  243.         short        i;
  244.  
  245.         err = LaunchSpeller( aliasHdl );
  246.         if ( err ){
  247.             DebugStr( "\pUnable to launch Word Services server" );
  248.             return err;
  249.         }
  250. #ifdef NEVER        
  251.         /* Got to sleep for a little while - otherwise the speller croaks */
  252.         for ( i = 0; i < 10; i++ )
  253.             WaitNextEvent( 0, &event, 1, (RgnHandle)NULL );
  254. #endif
  255.     }    
  256.  
  257.     err = AECreateDesc( typeApplSignature,
  258.                         (Ptr)&signature,
  259.                         sizeof( signature ),
  260.                         spellerAddrPtr );
  261.     if ( err ){
  262.         Gripe( "\pAECreateDesc failed" );
  263.         return err;
  264.     }
  265.     
  266.     return noErr;
  267. }
  268.  
  269. #ifdef NEVER
  270. OSErr LaunchSpeller( AliasHandle aliasHdl )
  271. {
  272.     OSErr        err;
  273.     FSSpec        spellerSpec;
  274.     Boolean        changed;
  275.     AppleEvent        launchEvent;
  276.     AppleEvent        replyEvent;
  277.     AEDesc            aliasDesc;
  278.     AEDesc            folderDesc;
  279.     FSSpec            folderSpec;
  280.     AEDesc            finderAddr;
  281.     DescType        finderSig;
  282.     AliasHandle        fAliasHdl;
  283.  
  284.     /* Make sure the speller can still be found, and get its spec */
  285.     err = ResolveAlias( (FSSpecPtr)NULL, aliasHdl, &spellerSpec, &changed );
  286.     
  287.     if ( err ){
  288.         Gripe( "\pCannot locate speller" );        /* Might be user canceled AShare */
  289.         return err;
  290.     }
  291.     
  292.     if ( changed ){
  293.         ChangedResource( aliasHdl );
  294.         WriteResource( aliasHdl );
  295.     }
  296.     
  297.     /* make an alias for the parent folder */
  298.     
  299.     err = FSMakeFSSpec( spellerSpec.vRefNum,
  300.                         spellerSpec.parID,
  301.                         (StringPtr)NULL,
  302.                         &folderSpec );
  303.     if ( err ){
  304.         Gripe( "\pMakeFSSpec failed" );
  305.         return err;
  306.     }
  307.     
  308.     err = NewAlias( (FSSpecPtr)NULL, &folderSpec, &fAliasHdl );
  309.     if ( err ){
  310.         Gripe( "\pNewAlias failed" );
  311.         return err;
  312.     }
  313.  
  314.     /* Create the event to send to the Finder */
  315.     
  316.     finderSig = 'MACS';                        /* Creator code of finder; type is 'FNDR' */
  317.     err = AECreateDesc( typeApplSignature,
  318.                         (Ptr)&finderSig,
  319.                         sizeof( finderSig ),
  320.                         &finderAddr );
  321.     if ( err ){
  322.         Gripe( "\pAECreateDesc failed" );
  323.         return err;
  324.     }    
  325.                 
  326.     err = AECreateAppleEvent( kAEFinderEvents,
  327.                                 kAEOpenSelection,
  328.                                 &finderAddr,
  329.                                 kAutoGenerateReturnID,
  330.                                 kAnyTransactionID,
  331.                                 &launchEvent );
  332.     
  333.     if ( err ){
  334.         Gripe( "\pcreate open selection event failed" );
  335.         return err;
  336.     }
  337.     err = AEDisposeDesc( &finderAddr );
  338.     if ( err ){
  339.         Gripe( "\pAEDisposeDesc failed" );
  340.         return err;
  341.     }
  342.     
  343.     /* Insert the folder alias record as the direct object of the batch event */
  344.  
  345.     /* First make a descriptor */
  346.     HLock( fAliasHdl );
  347.  
  348.     err = AECreateDesc( typeAlias,
  349.                         (Ptr)*fAliasHdl,
  350.                         (*fAliasHdl)->aliasSize,
  351.                         &folderDesc );
  352.  
  353.     HUnlock( fAliasHdl );
  354.     DisposHandle( fAliasHdl );
  355.  
  356.     if ( err ){
  357.         Gripe( "\pAECreateDesc failed" );
  358.         return err;
  359.     }    
  360.     
  361.     err = AEPutParamDesc( &launchEvent,
  362.                             keyDirectObject,
  363.                             &folderDesc );
  364.     if ( err ){
  365.         Gripe( "\pAEPutParamDesc failed to put direct object on open selection event" );
  366.         return err;
  367.     }
  368.     err = AEDisposeDesc( &folderDesc );
  369.     if ( err ){
  370.         Gripe( "\pAEDisposeDesc failed" );
  371.         return err;
  372.     }
  373.  
  374.     /* Put the application alias on the event */
  375.     HLock( aliasHdl );
  376.  
  377.     err = AECreateDesc( typeAlias,
  378.                         (Ptr)*aliasHdl,
  379.                         (*aliasHdl)->aliasSize,
  380.                         &aliasDesc );
  381.  
  382.     HUnlock( aliasHdl );
  383.  
  384.     if ( err ){
  385.         Gripe( "\pAECreateDesc failed" );
  386.         return err;
  387.     }    
  388.     
  389.     err = AEPutParamDesc( &launchEvent,
  390.                             keySelection,
  391.                             &aliasDesc );
  392.     if ( err ){
  393.         Gripe( "\pAEPutParamDesc failed to put keySelection on open selection event" );
  394.         return err;
  395.     }
  396.     err = AEDisposeDesc( &aliasDesc );
  397.     if ( err ){
  398.         Gripe( "\pAEDisposeDesc failed" );
  399.         return err;
  400.     }
  401.  
  402. #define kFewSeconds 300
  403.     
  404.     err = AESend( &launchEvent,
  405.                     &replyEvent,
  406.                     kAEWaitReply + kAECanInteract + kAECanSwitchLayer,
  407.                     kAENormalPriority,
  408.                     kFewSeconds,
  409.                     (IdleProcPtr)NULL,
  410.                     (EventFilterProcPtr)NULL );
  411.     
  412.     if ( err ){
  413.         Gripe( "\psend open selection event failed" );
  414.         return err;
  415.     }
  416.     err = AEDisposeDesc( &launchEvent );
  417.     if ( err ){
  418.         Gripe( "\pAEDisposeDesc failed" );
  419.         return err;
  420.     }
  421.     
  422.     return noErr;
  423. }
  424. #endif
  425.  
  426. /* This makes the speller fail to process the batch event - I don't know why */
  427.  
  428. OSErr LaunchSpeller( AliasHandle aliasHdl )
  429. {
  430.     LaunchParamBlockRec    pb;
  431.     OSErr        err;
  432.     FSSpec        spellerSpec;
  433.     Boolean        changed;
  434.     char        *cPtr;
  435.     short        i;
  436.     
  437.     /* Make sure the speller can still be found */
  438.     err = ResolveAlias( (FSSpecPtr)NULL, aliasHdl, &spellerSpec, &changed );
  439.     
  440.     if ( err ){
  441.         Gripe( "\pCannot locate speller" );        /* Might be user canceled AShare */
  442.         return err;
  443.     }
  444.     
  445.     if ( changed ){
  446.         ChangedResource( aliasHdl );
  447.         WriteResource( aliasHdl );
  448.     }
  449.     
  450.     cPtr = (char*)&pb;
  451.     
  452.     for ( i = 0; i < sizeof( pb ); i++ ){
  453.         *cPtr++ = 0;
  454.     }
  455.  
  456.     pb.launchBlockID = extendedBlock;
  457.     pb.launchEPBLength = extendedBlockLen;
  458.     pb.launchControlFlags = launchNoFileFlags + launchContinue /*+ launchDontSwitch*/;
  459.     pb.launchAppSpec = &spellerSpec;
  460.     pb.launchAppParameters = NULL;
  461.     
  462.     err = LaunchApplication( &pb );
  463.     
  464.     if ( err == memFullErr ){
  465.     
  466.         Gripe( "\pThere is not enough memory to launch the Word Services server" );
  467.         return err;
  468.     }
  469.     
  470.     if ( err ){
  471.         Gripe( "\pUnable to launch the Word Services server" );
  472.         return err;
  473.     }
  474.  
  475.     return noErr;
  476. }
  477.